//
// File: pwelch.cpp
//
// MATLAB Coder version            : 5.4
// C/C++ source code generated on  : 23-Apr-2025 16:26:18
//

// Include Files
#include "pwelch.h"
#include "colon.h"
#include "computeperiodogram.h"
#include "computepsd.h"
#include "freqDomainHRV_internal_types.h"
#include "ixfun.h"
#include "psdcenterdc.h"
#include "psdfreqvec.h"
#include "rt_nonfinite.h"
#include "welch.h"
#include "welchparse.h"
#include "coder_array.h"
#include <cmath>
#include <string.h>

// Function Definitions
//
// Arguments    : const ::coder::array<double, 2U> &x
//                double varargin_1
//                double varargin_2
//                double varargin_3
//                double varargin_4
//                ::coder::array<double, 2U> &varargout_1
//                ::coder::array<double, 1U> &varargout_2
// Return Type  : void
//
namespace coder {
void pwelch(const ::coder::array<double, 2U> &x, double varargin_1,
            double varargin_2, double varargin_3, double varargin_4,
            ::coder::array<double, 2U> &varargout_1,
            ::coder::array<double, 1U> &varargout_2)
{
  static const char varargin_5[8]{'o', 'n', 'e', 's', 'i', 'd', 'e', 'd'};
  array<double, 2U> Pxxc1;
  array<double, 2U> Sxx1;
  array<double, 2U> b_Sxx1;
  array<double, 2U> r;
  array<double, 2U> xEnd;
  array<double, 2U> xStart;
  array<double, 1U> Sxxk;
  array<double, 1U> b_x1;
  array<double, 1U> w;
  array<double, 1U> win1;
  array<double, 1U> x1;
  struct_T options;
  double L;
  double LminusOverlap;
  double k1;
  double noverlap;
  int units_size[2];
  int i;
  int loop_ub;
  char units_data[10];
  signal::internal::spectral::welchparse(
      x, varargin_1, varargin_2, varargin_3, varargin_4, varargin_5, x1,
      &LminusOverlap, win1, &noverlap, &k1, &L, &options);
  LminusOverlap = L - noverlap;
  noverlap = k1 * LminusOverlap;
  if (std::isnan(LminusOverlap) || std::isnan(noverlap)) {
    xStart.set_size(1, 1);
    xStart[0] = rtNaN;
  } else if ((LminusOverlap == 0.0) ||
             ((noverlap > 1.0) && (LminusOverlap < 0.0)) ||
             ((noverlap < 1.0) && (LminusOverlap > 0.0))) {
    xStart.set_size(1, 0);
  } else if (std::isinf(noverlap) && std::isinf(LminusOverlap)) {
    xStart.set_size(1, 1);
    xStart[0] = rtNaN;
  } else if (std::isinf(LminusOverlap)) {
    xStart.set_size(1, 1);
    xStart[0] = 1.0;
  } else if (std::floor(LminusOverlap) == LminusOverlap) {
    loop_ub = static_cast<int>((noverlap - 1.0) / LminusOverlap);
    xStart.set_size(1, loop_ub + 1);
    for (i = 0; i <= loop_ub; i++) {
      xStart[i] = LminusOverlap * static_cast<double>(i) + 1.0;
    }
  } else {
    eml_float_colon(LminusOverlap, noverlap, xStart);
  }
  xEnd.set_size(1, xStart.size(1));
  loop_ub = xStart.size(1);
  for (i = 0; i < loop_ub; i++) {
    xEnd[i] = (xStart[i] + L) - 1.0;
  }
  if (options.maxhold) {
    Sxx1.set_size(0, 0);
    i = static_cast<int>(k1);
    for (int ii{0}; ii < i; ii++) {
      int i1;
      int i2;
      LminusOverlap = xStart[ii];
      noverlap = xEnd[ii];
      if (LminusOverlap > noverlap) {
        i1 = 0;
        i2 = 0;
      } else {
        i1 = static_cast<int>(LminusOverlap) - 1;
        i2 = static_cast<int>(noverlap);
      }
      loop_ub = i2 - i1;
      b_x1.set_size(loop_ub);
      for (i2 = 0; i2 < loop_ub; i2++) {
        b_x1[i2] = x1[i1 + i2];
      }
      computeperiodogram(b_x1, win1, options.nfft, options.Fs, Sxxk, w);
      if (ii + 1U == 1U) {
        loop_ub = Sxxk.size(0);
        for (i1 = 0; i1 < loop_ub; i1++) {
          noverlap = k1 * Sxxk[i1];
          Sxxk[i1] = std::fmax(rtMinusInf, noverlap);
        }
        loop_ub = Sxxk.size(0);
        Sxx1.set_size(Sxxk.size(0), 1);
        for (i1 = 0; i1 < loop_ub; i1++) {
          Sxx1[i1] = Sxxk[i1];
        }
      } else {
        loop_ub = Sxxk.size(0);
        for (i1 = 0; i1 < loop_ub; i1++) {
          Sxxk[i1] = k1 * Sxxk[i1];
        }
        loop_ub = Sxx1.size(0);
        if ((Sxx1.size(0) == Sxxk.size(0)) && (Sxx1.size(1) == 1)) {
          Sxxk.set_size(Sxx1.size(0));
          for (i1 = 0; i1 < loop_ub; i1++) {
            LminusOverlap = Sxx1[i1];
            noverlap = Sxxk[i1];
            Sxxk[i1] = std::fmax(LminusOverlap, noverlap);
          }
          loop_ub = Sxxk.size(0);
          Sxx1.set_size(Sxxk.size(0), 1);
          for (i1 = 0; i1 < loop_ub; i1++) {
            Sxx1[i1] = Sxxk[i1];
          }
        } else {
          b_Sxx1.set_size(Sxx1.size(0), Sxx1.size(1));
          loop_ub = Sxx1.size(0) * Sxx1.size(1) - 1;
          for (i1 = 0; i1 <= loop_ub; i1++) {
            b_Sxx1[i1] = Sxx1[i1];
          }
          internal::expand_max(b_Sxx1, Sxxk, Sxx1);
        }
      }
    }
    loop_ub = Sxx1.size(0) * Sxx1.size(1);
    for (i = 0; i < loop_ub; i++) {
      Sxx1[i] = Sxx1[i] / k1;
    }
    psdfreqvec(options.nfft, options.Fs, w);
    loop_ub = w.size(0);
    xStart = w.reshape(loop_ub, 1);
    computepsd(Sxx1, xStart, options.range, options.nfft, options.Fs,
               varargout_1, varargout_2, units_data, units_size);
  } else if (options.minhold) {
    Sxx1.set_size(0, 0);
    i = static_cast<int>(k1);
    for (int ii{0}; ii < i; ii++) {
      int i1;
      int i2;
      LminusOverlap = xStart[ii];
      noverlap = xEnd[ii];
      if (LminusOverlap > noverlap) {
        i1 = 0;
        i2 = 0;
      } else {
        i1 = static_cast<int>(LminusOverlap) - 1;
        i2 = static_cast<int>(noverlap);
      }
      loop_ub = i2 - i1;
      b_x1.set_size(loop_ub);
      for (i2 = 0; i2 < loop_ub; i2++) {
        b_x1[i2] = x1[i1 + i2];
      }
      computeperiodogram(b_x1, win1, options.nfft, options.Fs, Sxxk, w);
      if (ii + 1U == 1U) {
        loop_ub = Sxxk.size(0);
        for (i1 = 0; i1 < loop_ub; i1++) {
          noverlap = k1 * Sxxk[i1];
          Sxxk[i1] = std::fmin(rtInf, noverlap);
        }
        loop_ub = Sxxk.size(0);
        Sxx1.set_size(Sxxk.size(0), 1);
        for (i1 = 0; i1 < loop_ub; i1++) {
          Sxx1[i1] = Sxxk[i1];
        }
      } else {
        loop_ub = Sxxk.size(0);
        for (i1 = 0; i1 < loop_ub; i1++) {
          Sxxk[i1] = k1 * Sxxk[i1];
        }
        loop_ub = Sxx1.size(0);
        if ((Sxx1.size(0) == Sxxk.size(0)) && (Sxx1.size(1) == 1)) {
          Sxxk.set_size(Sxx1.size(0));
          for (i1 = 0; i1 < loop_ub; i1++) {
            LminusOverlap = Sxx1[i1];
            noverlap = Sxxk[i1];
            Sxxk[i1] = std::fmin(LminusOverlap, noverlap);
          }
          loop_ub = Sxxk.size(0);
          Sxx1.set_size(Sxxk.size(0), 1);
          for (i1 = 0; i1 < loop_ub; i1++) {
            Sxx1[i1] = Sxxk[i1];
          }
        } else {
          b_Sxx1.set_size(Sxx1.size(0), Sxx1.size(1));
          loop_ub = Sxx1.size(0) * Sxx1.size(1) - 1;
          for (i1 = 0; i1 <= loop_ub; i1++) {
            b_Sxx1[i1] = Sxx1[i1];
          }
          internal::expand_min(b_Sxx1, Sxxk, Sxx1);
        }
      }
    }
    loop_ub = Sxx1.size(0) * Sxx1.size(1);
    for (i = 0; i < loop_ub; i++) {
      Sxx1[i] = Sxx1[i] / k1;
    }
    psdfreqvec(options.nfft, options.Fs, w);
    loop_ub = w.size(0);
    xStart = w.reshape(loop_ub, 1);
    computepsd(Sxx1, xStart, options.range, options.nfft, options.Fs,
               varargout_1, varargout_2, units_data, units_size);
  } else {
    Sxx1.set_size(0, 0);
    i = static_cast<int>(k1);
    for (int ii{0}; ii < i; ii++) {
      int i1;
      int i2;
      LminusOverlap = xStart[ii];
      noverlap = xEnd[ii];
      if (LminusOverlap > noverlap) {
        i1 = 0;
        i2 = 0;
      } else {
        i1 = static_cast<int>(LminusOverlap) - 1;
        i2 = static_cast<int>(noverlap);
      }
      loop_ub = i2 - i1;
      b_x1.set_size(loop_ub);
      for (i2 = 0; i2 < loop_ub; i2++) {
        b_x1[i2] = x1[i1 + i2];
      }
      computeperiodogram(b_x1, win1, options.nfft, options.Fs, Sxxk, w);
      if (ii + 1U == 1U) {
        loop_ub = Sxxk.size(0);
        Sxx1.set_size(Sxxk.size(0), 1);
        for (i1 = 0; i1 < loop_ub; i1++) {
          Sxx1[i1] = Sxxk[i1];
        }
      } else if (Sxx1.size(0) == Sxxk.size(0)) {
        loop_ub = Sxx1.size(1);
        b_Sxx1.set_size(Sxx1.size(0), Sxx1.size(1));
        for (i1 = 0; i1 < loop_ub; i1++) {
          int b_loop_ub;
          b_loop_ub = Sxx1.size(0);
          for (i2 = 0; i2 < b_loop_ub; i2++) {
            b_Sxx1[i2] = Sxx1[i2] + Sxxk[i2];
          }
        }
        Sxx1.set_size(b_Sxx1.size(0), b_Sxx1.size(1));
        loop_ub = b_Sxx1.size(0) * b_Sxx1.size(1);
        for (i1 = 0; i1 < loop_ub; i1++) {
          Sxx1[i1] = b_Sxx1[i1];
        }
      } else {
        binary_expand_op(Sxx1, Sxxk);
      }
    }
    loop_ub = Sxx1.size(0) * Sxx1.size(1);
    for (i = 0; i < loop_ub; i++) {
      Sxx1[i] = Sxx1[i] / k1;
    }
    psdfreqvec(options.nfft, options.Fs, w);
    loop_ub = w.size(0);
    xStart = w.reshape(loop_ub, 1);
    computepsd(Sxx1, xStart, options.range, options.nfft, options.Fs,
               varargout_1, varargout_2, units_data, units_size);
  }
  if (options.centerdc) {
    b_Sxx1.set_size(varargout_1.size(0), varargout_1.size(1));
    loop_ub = varargout_1.size(0) * varargout_1.size(1) - 1;
    for (i = 0; i <= loop_ub; i++) {
      b_Sxx1[i] = varargout_1[i];
    }
    r.set_size(0, 0);
    x1.set_size(varargout_2.size(0));
    loop_ub = varargout_2.size(0) - 1;
    for (i = 0; i <= loop_ub; i++) {
      x1[i] = varargout_2[i];
    }
    signal::internal::spectral::psdcenterdc(b_Sxx1, x1, r, options, varargout_1,
                                            varargout_2, Pxxc1);
  }
}

} // namespace coder

//
// File trailer for pwelch.cpp
//
// [EOF]
//
